home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 11 - 1995 / 11.02 Feb 95 / Yenta / Erics C++ Libraries / Interface Classes / CPPText.cp < prev    next >
Encoding:
Text File  |  1996-04-04  |  30.1 KB  |  1,183 lines  |  [TEXT/KAHL]

  1. /********************************************************* DEFINITION
  2.     DATE:    9/19/93
  3.     AUTHOR: Eric R. Rosé
  4.     
  5.     CLASS:  CPPText
  6.     
  7.     SUPERCLASS: CPPObject
  8.     
  9.         This C++ class manages a textedit area, and a horizontal and
  10.         vertical scrollbar which let you adjust the text.
  11.     
  12. ********************************************************************/
  13.  
  14. #include <stdlib.h>
  15. #include <CPPText.h>
  16. #include <CPPWindow.h>
  17. #include <ctype.h>
  18. #include <Commands.h>
  19. #include <mathTools.h>
  20.  
  21. extern Rect kEmptyRect;
  22.  
  23. /*-----------------------------------------------------------------*/
  24. /*---------------------- CALLBACK VARIABLES -----------------------*/
  25. /*-----------------------------------------------------------------*/
  26.  
  27.     // Initialize the class member variables used in the callbacks
  28.     CPPText *CPPText::gCurrentTE = NULL;
  29.     ControlHandle CPPText::gVScroll = NULL;
  30.     ControlHandle CPPText::gHScroll = NULL;
  31.     TEHandle CPPText::gTextBlock = NULL;
  32.  
  33. /*-----------------------------------------------------------------*/
  34. /*------------------------ PUBLIC METHODS -------------------------*/
  35. /*-----------------------------------------------------------------*/
  36.  
  37.     CPPText::CPPText (CPPWindow *OurWindow,
  38.                               Rect *ViewArea,
  39.                               Rect *DestArea,
  40.                               short    MaxLength,
  41.                               Boolean UseHScroll,
  42.                               Boolean UseVScroll,
  43.                               short Font, short FSize) :
  44.                 CPPVisualObject (OurWindow, ViewArea, TRUE)
  45.     {
  46.         MakeTEArea (OurWindow, ViewArea, DestArea, MaxLength, 
  47.                     UseHScroll, UseVScroll, Font, FSize);
  48.     }
  49.  
  50. /*-----------------------------------------------------------------*/
  51.  
  52.     CPPText::CPPText (CPPWindow *OurWindow,
  53.                               short    MaxLength,
  54.                               Boolean UseHScroll,
  55.                               Boolean UseVScroll,
  56.                               short Font, short FSize) :
  57.                 CPPVisualObject (OurWindow,
  58.                                  &((OurWindow->GetWindow())->portRect), 
  59.                                    TRUE)
  60.     {
  61.         Rect    ViewRect;
  62.         Rect    DestRect;
  63.         
  64.         if (OurWindow)
  65.           {
  66.               ViewRect = (OurWindow->GetWindow())->portRect;
  67.               SetRect (&DestRect, 0, 0, kPageWidth, kPageHeight);
  68.               MakeTEArea(OurWindow, &ViewRect, &DestRect, MaxLength,
  69.                           UseHScroll, UseVScroll, Font, FSize);
  70.           }
  71.     }
  72.     
  73. /*-----------------------------------------------------------------*/
  74.     
  75.     CPPText::~CPPText (void)
  76.     /* Dispose of the controls and TEHandle used by the object */
  77.     {
  78.         if (this->TextBlock)
  79.           TEDispose(this->TextBlock);
  80.         if (this->HScroll)
  81.           DisposeControl(this->HScroll);
  82.         if (this->VScroll)
  83.           DisposeControl(this->VScroll);
  84.     }
  85.  
  86. /*-----------------------------------------------------------------*/
  87.  
  88.     char    *CPPText::ClassName (void)
  89.     {
  90.         return "CPPText";
  91.     }
  92.  
  93. /*-----------------------------------------------------------------*/
  94.  
  95.     Boolean    CPPText::DoCommand (short commandID)
  96.     /* do a command associated with a menu */
  97.     {
  98.         switch (commandID) {
  99.             case kCmdCut :
  100.                 DoCut();
  101.                 break;
  102.             case kCmdCopy :    
  103.                 DoCopy();
  104.                 break;
  105.             case kCmdPaste :
  106.                 DoPaste();
  107.                 break;
  108.             case kCmdSelectAll :
  109.                 DoSelectAll();
  110.                 break;
  111.             case kCmdClear :
  112.                 if (this->TextBlock)
  113.                   TEDelete(this->TextBlock);
  114.                 break;
  115.             default:
  116.                 return FALSE;
  117.                 break;
  118.         }
  119.         
  120.         return TRUE;
  121.     }
  122.  
  123. /*-----------------------------------------------------------------*/
  124.  
  125.     void CPPText::SetMinSize (short mwidth, short mheight)
  126.     {
  127.         this->TEminWidth = mwidth;
  128.         this->TEminHeight = mheight;
  129.     }
  130.  
  131. /*-----------------------------------------------------------------*/
  132.  
  133.     void CPPText::SetMaxSize (short mwidth, short mheight)
  134.     {
  135.         this->TEmaxWidth = mwidth;
  136.         this->TEmaxHeight = mheight;
  137.     }
  138.  
  139. /*-----------------------------------------------------------------*/
  140.  
  141.     void CPPText::Activate (Boolean nowActive)
  142.     /* activate or deactivate the text depending on DoActivate */
  143.     /* Is Override */
  144.     {
  145.         short    HiliteValue = (nowActive) ? 0 : 255;
  146.         
  147.         CPPVisualObject::Activate(nowActive);
  148.         
  149.         if (this->TextBlock)
  150.           {
  151.             if (nowActive)
  152.               TEActivate(this->TextBlock);
  153.             else
  154.               TEDeactivate (this->TextBlock);
  155.             AdjustScrollBar();
  156.             
  157.             if (this->VScroll)
  158.               HiliteControl (this->VScroll, HiliteValue);
  159.             if (this->HScroll)
  160.               HiliteControl (this->HScroll, HiliteValue);
  161.           }
  162.     }
  163.  
  164. /*-----------------------------------------------------------------*/
  165.  
  166.     void CPPText::DoIdle (void)
  167.     /* Is Override */
  168.     {
  169.         if (this->IsActive() && this->TextBlock)
  170.           TEIdle(this->TextBlock);
  171.     }
  172.  
  173. /*-----------------------------------------------------------------*/
  174.  
  175.     void CPPText::TypeChar (unsigned char TheKey)
  176.     /* type a character into the TE area at the current insertion point */
  177.     {
  178.         Boolean    canType = TRUE;
  179.         short    SelectionLen = 0;
  180.         
  181.         if (this->TextBlock)
  182.           {
  183.               SelectionLen = (*this->TextBlock)->selEnd - 
  184.                              (*this->TextBlock)->selStart; 
  185.               if (isprint(TheKey))
  186.                 canType = (*this->TextBlock)->teLength - SelectionLen < 
  187.                                 this->maxTextLen;
  188.             if (canType)
  189.               {
  190.                 TEKey(TheKey, this->TextBlock);
  191.                 AdjustScrollBar();    
  192.                 CheckInsertion();
  193.               }
  194.           }
  195.     }
  196.  
  197. /*-----------------------------------------------------------------*/
  198.  
  199.     void CPPText::DoCut (void)
  200.     /* cut the current selection of the TE area */
  201.     {
  202.         long    dummy;
  203.         
  204.         if (this->TextBlock)
  205.           {
  206.             CheckInsertion();
  207.             TECut (this->TextBlock);
  208.             AdjustScrollBar();
  209.             CheckInsertion();
  210.             dummy = ZeroScrap();
  211.             dummy = TEToScrap();
  212.           }
  213.     }
  214.  
  215. /*-----------------------------------------------------------------*/
  216.  
  217.     void CPPText::DoCopy (void)
  218.     /* copy the current selection of the TE area */
  219.     {
  220.         long    dummy;
  221.     
  222.         if (this->TextBlock)
  223.           {
  224.             AdjustScrollBar();
  225.             TECopy (this->TextBlock);
  226.             dummy = ZeroScrap();
  227.             dummy = TEToScrap();
  228.           }
  229.     }
  230.  
  231. /*-----------------------------------------------------------------*/
  232.  
  233.     void CPPText::DoPaste (void)
  234.     /* paste the contents of the scrap into the TE area */
  235.     {
  236.         long    dummy;
  237.         short    SelectionLen;
  238.     
  239.         if (this->TextBlock)
  240.           {
  241.               SelectionLen = (*this->TextBlock)->selEnd - 
  242.                              (*this->TextBlock)->selStart; 
  243.               if (TEFromScrap() != noErr)
  244.                 SysBeep(5);
  245.               else
  246.                 {
  247.                 CheckInsertion();
  248.                 if ((TEGetScrapLen() + 
  249.                     (*this->TextBlock)->teLength -
  250.                     SelectionLen) <= this->maxTextLen)
  251.                   {    // if the selection will fit, paste it in
  252.                     TEPaste (this->TextBlock);
  253.                     AdjustScrollBar();
  254.                     CheckInsertion();
  255.                   }
  256.                 else    // change the scrap size and paste
  257.                   {
  258.                       TESetScrapLen(this->maxTextLen - 
  259.                                     (*this->TextBlock)->teLength + 
  260.                                     SelectionLen);
  261.                     TEPaste (this->TextBlock);
  262.                     AdjustScrollBar();
  263.                     CheckInsertion();
  264.                   }
  265.                 }
  266.           }
  267.     }
  268.  
  269. /*-----------------------------------------------------------------*/
  270.  
  271.     void CPPText::DoClear (void)
  272.     /* Clear the current selection in the TE area */
  273.     {
  274.         long    dummy;
  275.     
  276.         if (this->TextBlock)
  277.           {
  278.             CheckInsertion();
  279.             TEDelete (this->TextBlock);
  280.             AdjustScrollBar();
  281.             CheckInsertion();
  282.           }
  283.     }
  284.  
  285. /*-----------------------------------------------------------------*/
  286.  
  287.     void CPPText::DoSelectAll (void)
  288.     /* select all of the text in the TE area */
  289.     {
  290.         if (this->TextBlock)
  291.           {
  292.             CheckInsertion();
  293.             TESetSelect(0, 32000, this->TextBlock);
  294.             AdjustScrollBar();
  295.             CheckInsertion();
  296.           }
  297.     }
  298.  
  299. /*-----------------------------------------------------------------*/
  300.  
  301.     short    CPPText::GetTextLen (void)
  302.     {
  303.         if (this->TextBlock)
  304.           return (**this->TextBlock).teLength;
  305.         else
  306.           return 0;
  307.     }
  308.  
  309. /*-----------------------------------------------------------------*/
  310.  
  311.     CharsHandle    CPPText::GetTheText (void)
  312.     /* return a handle to the text in the TE object */
  313.     {
  314.         if (this->TextBlock)
  315.           return TEGetText (this->TextBlock);
  316.         else
  317.           return NULL;
  318.     }
  319.  
  320. /*-----------------------------------------------------------------*/
  321.     
  322.     Boolean    CPPText::DoKey (char theKey, short modifiers, short what)
  323.     {
  324.         if (!IsVisible()) return FALSE;
  325.         
  326.         if (modifiers & cmdKey) 
  327.           {        /* Command key down. */
  328.             if (what == keyDown) 
  329.               {    // handle default edit commands
  330.                 switch (theKey) {
  331.                     case 'x' :
  332.                     case 'X' : DoCut(); break;
  333.                     case 'c' :
  334.                     case 'C' : DoCopy(); break;
  335.                     case 'v' :
  336.                     case 'V' : DoPaste(); break;
  337.                     case 'a' :
  338.                     case 'A' : DoSelectAll(); break;
  339.                     default  : return FALSE;    // unknown command
  340.                         break;
  341.                 }
  342.                 return TRUE;    // we handled the cut/copy/paste
  343.                 }
  344.           }
  345.         else
  346.           TypeChar (theKey);
  347.     }
  348.  
  349. /*-----------------------------------------------------------------*/
  350.  
  351.     Boolean CPPText::DoClick (EventRecord *theEvent)
  352.     /* Is Override */
  353.     {
  354.         WindowPtr    theWindow;
  355.         short        code, part;
  356.         ControlHandle    hitControl;
  357.         Point        myPt = theEvent->where;
  358.         TEPtr        TE;
  359.         Boolean        shiftDown = (theEvent->modifiers & shiftKey) ? TRUE : FALSE;
  360.         
  361.         if (!IsVisible()) return FALSE;
  362.         
  363.           code = FindWindow(theEvent->where, &theWindow);
  364.           if (theWindow == this->owningWindow)
  365.             {
  366.               Global2Local (&myPt);
  367.             part = FindControl(myPt, theWindow, &hitControl);
  368.             
  369.             // now respond to the click
  370.             if (hitControl)        // if they clicked in a scrollbar
  371.               {
  372.                 if (hitControl == this->HScroll)
  373.                   DoHScroller (myPt, part);
  374.                 else
  375.                 if (hitControl ==  this->VScroll)
  376.                   DoVScroller (myPt, part);
  377.                 else
  378.                   return FALSE;
  379.               }
  380.             else                // if they clicked in the TE area
  381.               {
  382.                   if (this->TextBlock)
  383.                     {
  384.                         TE = *this->TextBlock;
  385.                         if (PtInRect(myPt, &TE->viewRect))
  386.                           {
  387.                               gVScroll = this->VScroll;
  388.                               gHScroll = this->HScroll;
  389.                               gTextBlock = this->TextBlock;
  390.                               gCurrentTE = this;
  391.                             TEClick (myPt, shiftDown, this->TextBlock);
  392.                           }
  393.                         else
  394.                           return FALSE;
  395.                     }
  396.                   else
  397.                     return FALSE;
  398.               }    
  399.             }
  400.     }
  401.  
  402. /*-----------------------------------------------------------------*/
  403.  
  404.     void CPPText::InsertTextPtr (Ptr theText, long textLen, 
  405.                                     long insertWhere, 
  406.                                     Boolean ScrollToInsertion)
  407.     /* insert the text pointed to by TheText into the TE area */
  408.     /* at the specified location */
  409.     {
  410.         short    maxAllowed;        // use to keep within length limits
  411.         
  412.         if (this->TextBlock && theText)
  413.           {
  414.               maxAllowed = this->maxTextLen - (*this->TextBlock)->teLength;
  415.               
  416.               // let us watch what's going on
  417.             if (ScrollToInsertion)
  418.               CheckInsertion();
  419.             
  420.             // set the selection and insert
  421.             TESetSelect(insertWhere, insertWhere, this->TextBlock);
  422.             TEInsert(theText, Min(maxAllowed, textLen), this->TextBlock);
  423.             
  424.             // adjust for the text we inserted
  425.             if (ScrollToInsertion)
  426.               CheckInsertion();
  427.           }
  428.     }
  429.  
  430. /*-----------------------------------------------------------------*/
  431.  
  432.     void CPPText::InsertTextHandle (Handle theText, long textLen,
  433.                                         long where, 
  434.                                         Boolean ScrollToInsertion)
  435.     /* insert the text pointed to by TheText into the TE area */
  436.     /* in place of/at the current selection */
  437.     {
  438.         Boolean    wasLocked;
  439.         
  440.         if (this->TextBlock && theText)
  441.           {
  442.               wasLocked = (HGetState(theText) & 0x0080) ? TRUE : FALSE;
  443.               HLock(theText);
  444.  
  445.               InsertTextPtr (*theText, textLen, where, ScrollToInsertion);
  446.               
  447.               if (!wasLocked)
  448.                 HUnlock(theText);
  449.           }
  450.         
  451.     }
  452.  
  453. /*-----------------------------------------------------------------*/
  454.  
  455.     void CPPText::SetTextPtr (Ptr theText, long textLen,
  456.                                   Boolean ScrollToInsertion)
  457.     /* set the TE area to contain only the text pointed to by TheText */
  458.     {
  459.         DoSelectAll();        // select all the text in the area
  460.         DoClear();            // delete it all
  461.         InsertTextPtr(theText, Min(textLen, this->maxTextLen), 
  462.                       1, ScrollToInsertion);
  463.     }
  464.  
  465. /*-----------------------------------------------------------------*/
  466.  
  467.     void CPPText::SetTextHandle (Handle theText, long textLen,
  468.                                      Boolean ScrollToInsertion)
  469.     /* set the TE area to contain only the text pointed to by TheText */
  470.     {
  471.         DoSelectAll();        // select all the text in the area
  472.         DoClear();            // delete it all
  473.         InsertTextHandle(theText, Min(textLen, this->maxTextLen), 
  474.                          1, ScrollToInsertion);
  475.     }
  476.  
  477. /*-----------------------------------------------------------------*/
  478.  
  479.     void    CPPText::MakeVisible (Boolean nowVisible)
  480.     /* Hide or show the text edit area, depending on 'nowVisible' */
  481.     {    
  482.         Rect    boundsRect = *GetBounds();
  483.     
  484.         InsetRect (&boundsRect, -1, -1);
  485.         // exit if it is already in the desired state
  486.         if (nowVisible == IsVisible())
  487.           return;
  488.         
  489.         CPPVisualObject::MakeVisible (nowVisible);
  490.  
  491.         // if it is currently invisible, erase it;
  492.         // in either case, invalidate the area to force a redraw
  493.         if (!IsVisible())
  494.           {
  495.             EraseRect (&boundsRect);
  496.             if (this->VScroll)
  497.               HideControl(VScroll);
  498.             if (this->HScroll)
  499.               HideControl(HScroll);
  500.           }
  501.         else
  502.           {
  503.             if (this->VScroll)
  504.               ShowControl(VScroll);
  505.             if (this->HScroll)
  506.               ShowControl(HScroll);
  507.             this->Draw();
  508.           }
  509.           
  510.         InvalRect(&boundsRect);
  511.         
  512.     }
  513.  
  514. /*-----------------------------------------------------------------*/
  515.     
  516.     void CPPText::Draw (void)
  517.     /* draw the text edit area and its controls */
  518.     {
  519.         Rect    tempRect;
  520.         if (this->owningWindow && this->TextBlock && this->IsVisible())
  521.           {
  522.               tempRect = (*this->TextBlock)->viewRect;
  523.               InsetRect (&tempRect, -1, -1);
  524.               FrameRect(&tempRect);
  525.             TEUpdate (&this->owningWindow->portRect, this->TextBlock);
  526.                if (this->VScroll)
  527.                  Draw1Control (this->VScroll);
  528.                if (this->HScroll)
  529.                  Draw1Control (this->HScroll);
  530.           }
  531.     }
  532.     
  533. /*-----------------------------------------------------------------*/
  534.  
  535.     void    CPPText::TargetHilite (Boolean makeTarget)
  536.     /* change the hiliteed state of the object (some objects, like */
  537.     /* lists, have different appearances when they are the target) */
  538.     /* SUBCLASS SHOULD OVERRIDE */
  539.     {
  540.         this->Activate(makeTarget);
  541.         
  542.         CPPVisualObject::TargetHilite(makeTarget);
  543.     }
  544.  
  545. /*-----------------------------------------------------------------*/
  546.  
  547.     Rect    *CPPText::GetBounds (void)
  548.     /* return the boundsrect of the object */
  549.     /* SUBCLASS MUST OVERRIDE */
  550.     {    
  551.         SetRect (&this->bounds, 0, 0, 0, 0);
  552.         
  553.         if (this->isVisible)
  554.           {
  555.             if (this->TextBlock)
  556.               this->bounds = (*this->TextBlock)->viewRect;
  557.             if (this->VScroll)
  558.               UnionRect (&this->bounds, &((*this->VScroll)->contrlRect), &this->bounds);
  559.             if (this->HScroll)
  560.               UnionRect (&this->bounds, &((*this->HScroll)->contrlRect), &this->bounds);
  561.           }
  562.         else
  563.           this->bounds = kEmptyRect;
  564.         
  565.         return &this->bounds;
  566.     }
  567.  
  568.  
  569. /*-----------------------------------------------------------------*/
  570. /*---------------------- PROTECTED METHODS ------------------------*/
  571. /*-----------------------------------------------------------------*/
  572.  
  573.     void    CPPText::MoveContent (short newH, short newV)
  574.     /* move the entire text edit area to the new position */
  575.     {
  576.         Rect        vRect, dRect, bRect = *GetBounds();
  577.         short        deltaH = newH - bRect.left,
  578.                      deltaV = newV - bRect.top;
  579.             
  580.         // move the text block
  581.         if (this->TextBlock)
  582.           {
  583.               vRect = (*this->TextBlock)->viewRect;
  584.               dRect = (*this->TextBlock)->destRect;
  585.             OffsetRect (&((*this->TextBlock)->viewRect), newH-dRect.left, 
  586.                             newV-dRect.top);
  587.             OffsetRect (&((*this->TextBlock)->destRect), newH-dRect.left, 
  588.                             newV-dRect.top);
  589.           }
  590.         // move the vertical scroll bar
  591.         if (this->VScroll)
  592.           {
  593.               vRect = (*this->VScroll)->contrlRect;
  594.               MoveControl (this->VScroll, vRect.left + deltaH, 
  595.                                            vRect.top + deltaV);
  596.           }
  597.         // move the horizontal scroll bar
  598.         if (this->HScroll)
  599.           {
  600.               dRect = (*this->HScroll)->contrlRect;
  601.               MoveControl (this->HScroll, dRect.left + deltaH, 
  602.                                            dRect.top + deltaV);
  603.           }
  604.     }
  605.  
  606. /*-----------------------------------------------------------------*/
  607.  
  608.     void CPPText::ResizeContent (short newWidth, short newHeight)
  609.     {
  610.                     
  611.         TEPtr    TE = (this->TextBlock) ? *this->TextBlock : NULL;
  612.         Rect    VCRect, HCRect, GrowRect, ViewRect, DestRect;
  613.         Rect    PRect;
  614.         
  615.         if (this->owningWindow && this->TextBlock)
  616.           {
  617.               // figure out what the new size of the view area is
  618.               ViewRect = TE->viewRect;
  619.               ViewRect.right = Min (ViewRect.left + newWidth, this->TEmaxWidth)
  620.                                   - ((this->VScroll) ? 15 : 0);
  621.               ViewRect.bottom = Min (ViewRect.top + newHeight, this->TEmaxHeight)
  622.                                   - ((this->HScroll) ? 15 : 0);
  623.               
  624.               // move and resize the controls
  625.               if (this->HScroll)
  626.                 {
  627.                     HideControl (this->HScroll);
  628.                     MoveControl (this->HScroll, ViewRect.left-1, ViewRect.bottom);
  629.                     SizeControl (this->HScroll, (ViewRect.right - ViewRect.left) + 2, 16);
  630.                     ShowControl (this->HScroll);
  631.                 }
  632.  
  633.               if (this->VScroll)
  634.                 {
  635.                     HideControl (this->VScroll);
  636.                     MoveControl (this->VScroll, ViewRect.right, ViewRect.top-1);
  637.                     SizeControl (this->VScroll, 16, (ViewRect.bottom - ViewRect.top) + 2);
  638.                     ShowControl (this->VScroll);
  639.                 }
  640.               
  641.               // resize the text edit area
  642.               TE->viewRect = ViewRect;
  643.               
  644.               // adjust the positions of everything
  645.               AdjustScrollBar();
  646.               CheckInsertion();
  647.           }
  648.     }    
  649.  
  650. /*-----------------------------------------------------------------*/
  651.  
  652.     void CPPText::CheckInsertion (void)
  653.     /* this procedure checks the current insertion point and adjusts */
  654.     /* the text in the window so that the insertion point is always */
  655.     /* visible */
  656.     {
  657.         short    topLine, bottomLine, windowLines;
  658.         TEPtr    TE;
  659.         
  660.         if (this->VScroll && this->TextBlock)
  661.           {
  662.               TE = *this->TextBlock;
  663.               windowLines = LinesInWindow();
  664.               topLine = GetCtlValue (this->VScroll);
  665.               bottomLine = topLine + windowLines;
  666.           
  667.               if (GetCtlMax (this->VScroll) == 0)
  668.                 MoveScrollText();
  669.               else
  670.                 if (TE->selEnd < TE->lineStarts[topLine])
  671.                   ScrollChar (TE->selStart, FALSE);
  672.                 else
  673.                   if (TE->selStart >= TE->lineStarts[bottomLine])
  674.                     ScrollChar (TE->selEnd, TRUE);
  675.           }
  676.     }
  677.  
  678. /*-----------------------------------------------------------------*/
  679.  
  680.       void CPPText::ScrollChar (short charPos, Boolean toBottom)
  681.       /* Adjust the scroll bar to match the current position of the */
  682.       /* text after text has been inserted or deleted */
  683.     {
  684.         short    theLine = 0;
  685.         TEPtr    TE;
  686.         
  687.         if (this->TextBlock && this->VScroll)
  688.           {
  689.               TE = *this->TextBlock;
  690.               while (TE->lineStarts[theLine+1] <= charPos)
  691.                 theLine++;
  692.               if (toBottom)
  693.                 theLine = theLine - (LinesInWindow() - 1);
  694.               SetCtlValue(this->VScroll, theLine);
  695.               MoveScrollText();
  696.           }
  697.     }
  698.     
  699. /*-----------------------------------------------------------------*/
  700. /*----------------------- PRIVATE METHODS -------------------------*/
  701. /*-----------------------------------------------------------------*/
  702.  
  703.     long CPPText::LinesInWindow(void)
  704.     {
  705.         TEPtr    TE = (this->TextBlock) ? *this->TextBlock : NULL;
  706.         
  707.         if (TE)
  708.           return (TE->viewRect.bottom - TE->viewRect.top) / 
  709.                     TE->lineHeight;
  710.         else
  711.           return 0;
  712.     }
  713.  
  714. /*-----------------------------------------------------------------*/
  715.  
  716.     long    CPPText::LinesInText (void)
  717.     {
  718.         long    Lines;
  719.         short    Len;
  720.         TEPtr    TE;
  721.         
  722.         if (this->TextBlock)
  723.           {
  724.               TE = *this->TextBlock;
  725.             Len = TE->teLength;
  726.             
  727.               Lines = TE->nLines;
  728.               if (Len > 0)
  729.                 if (*(*TE->hText + Len-1) == 13)
  730.                   Lines += 1;
  731.               return Lines;
  732.           }
  733.         else
  734.           return 0;
  735.     }
  736.     
  737. /*-----------------------------------------------------------------*/
  738.  
  739.     void CPPText::MoveScrollText ()
  740.     /* Scroll the text to match the settings of the scrollbars */
  741.     {
  742.         long    ScrollValue,
  743.                 height, i, j, 
  744.                 HScrollDiff = 0, VScrollDiff = 0,
  745.                 OldScroll, NewScroll;
  746.         TEPtr    TE;
  747.         
  748.         if (this->TextBlock)
  749.           {
  750.               TE = *this->TextBlock;
  751.             if (this->VScroll)
  752.               {
  753.                   OldScroll = TE->viewRect.top - TE->destRect.top;
  754.                   ScrollValue = GetCtlValue (this->VScroll);
  755.                   NewScroll = ScrollValue * TE->lineHeight;
  756.                   VScrollDiff = OldScroll - NewScroll;
  757.               }          
  758.  
  759.             if (this->HScroll)
  760.               {
  761.                   OldScroll = TE->viewRect.left - TE->destRect.left;
  762.                   ScrollValue = GetCtlValue (this->HScroll);
  763.                   NewScroll = ScrollValue * TE->lineHeight;
  764.                   HScrollDiff = OldScroll - NewScroll;
  765.               }          
  766.  
  767.               if (abs(VScrollDiff) > 32000)
  768.                 {        // if we have reached the limit of textedit, scroll & beep
  769.                     TEScroll (HScrollDiff, SIGN(VScrollDiff) * 32000, this->TextBlock);
  770.                     SysBeep(2);
  771.                 }
  772.             else    // otherwise, do the scrolling, if any is required
  773.               if (VScrollDiff + HScrollDiff != 0)
  774.                   TEScroll (HScrollDiff, VScrollDiff, this->TextBlock);
  775.         }
  776.     }
  777.  
  778. /*-----------------------------------------------------------------*/
  779.  
  780.     pascal void CPPText::Scroll_Up (ControlHandle theControl, short ctlPart)
  781.     /* this method serves as a callback routine for TrackControl; */
  782.     /* It forces the text to scroll up 1 line */
  783.     {
  784.         if (theControl && (GetCtlValue(theControl) - 1 >= GetCtlMin(theControl)))
  785.           {
  786.               SetCtlValue (theControl, GetCtlValue (theControl)-1);
  787.               gCurrentTE->MoveScrollText();
  788.           }    
  789.     }
  790.  
  791. /*-----------------------------------------------------------------*/
  792.  
  793.     pascal void CPPText::Scroll_Down (ControlHandle theControl, 
  794.                                         short ctlPart)
  795.     /* this method serves as a callback routine for TrackControl; */
  796.     /* It forces the text to scroll down 1 line */
  797.     {
  798.         if (theControl && (GetCtlValue(theControl) + 1 <= GetCtlMax(theControl)))
  799.           {
  800.               SetCtlValue (theControl, GetCtlValue (theControl)+1);
  801.               gCurrentTE->MoveScrollText();
  802.           }    
  803.     }
  804.  
  805. /*-----------------------------------------------------------------*/
  806.  
  807.     pascal void CPPText::Scroll_Left (ControlHandle theControl, 
  808.                                         short ctlPart)
  809.     /* this method serves as a callback routine for TrackControl; */
  810.     /* It forces the text to scroll left 1 line */
  811.     {
  812.         if (theControl && (GetCtlValue(theControl) - 1 >= GetCtlMin(theControl)))
  813.           {
  814.               SetCtlValue (theControl, GetCtlValue (theControl)-1);
  815.               gCurrentTE->MoveScrollText();
  816.           }    
  817.     }
  818.  
  819. /*-----------------------------------------------------------------*/
  820.  
  821.     pascal void CPPText::Scroll_Right (ControlHandle theControl, 
  822.                                         short ctlPart)
  823.     /* this method serves as a callback routine for TrackControl; */
  824.     /* It forces the text to scroll right 1 line */
  825.     {
  826.         if (theControl && (GetCtlValue(theControl) + 1 <= GetCtlMax(theControl)))
  827.           {
  828.               SetCtlValue (theControl, GetCtlValue (theControl)+1);
  829.               gCurrentTE->MoveScrollText();
  830.           }    
  831.     }
  832.  
  833. /*-----------------------------------------------------------------*/
  834.  
  835.     pascal Boolean CPPText::AutoScroll (void)
  836.     {
  837.         Boolean    result = TRUE;
  838.         RgnHandle    oldClip = NewRgn();
  839.         Point        mouseLoc;
  840.         Rect        textRect, tempRect;
  841.         
  842.         GetClip (oldClip);
  843.         tempRect = (*gTextBlock)->viewRect;
  844.         if (gVScroll)
  845.           UnionRect (&tempRect, &(*gVScroll)->contrlRect, &tempRect);
  846.         if (gHScroll)
  847.           UnionRect (&tempRect, &(*gHScroll)->contrlRect, &tempRect);
  848.         ClipRect(&tempRect);
  849.         
  850.         GetMouse (&mouseLoc);
  851.         textRect = (*gTextBlock)->viewRect;
  852.         if (mouseLoc.v < textRect.top)
  853.           Scroll_Up (gVScroll, inUpButton);
  854.         else
  855.           if (mouseLoc.v > textRect.bottom)
  856.             Scroll_Down (gVScroll, inDownButton);
  857.  
  858.         if (mouseLoc.h > textRect.right)
  859.           Scroll_Right (gHScroll, inDownButton);
  860.         else
  861.           if (mouseLoc.h < textRect.left)
  862.             Scroll_Left (gHScroll, inUpButton);
  863.           
  864.         SetClip (oldClip);
  865.         DisposeRgn(oldClip);
  866.         return TRUE;
  867.           
  868.     }
  869.  
  870. /*-----------------------------------------------------------------*/
  871.  
  872.     void    CPPText::VPageScroll (long part, long direction)
  873.     /* Scroll the text 1 page either up or down */
  874.     {
  875.         Point    tempPt;
  876.         short    newValue, page;
  877.         TEPtr    TE;
  878.         
  879.         if (this->VScroll && this->TextBlock)
  880.           {
  881.               TE = *this->TextBlock;
  882.               GetMouse (&tempPt);
  883.               while (StillDown())
  884.                 {
  885.                     if (TestControl(this->VScroll, tempPt) == part)
  886.                       {
  887.                           page = direction * ((TE->viewRect.top - 
  888.                                               TE->viewRect.bottom) / 
  889.                                               (TE->lineHeight - 1));
  890.                           newValue = GetCtlValue (this->VScroll) + page;
  891.                           SetCtlValue (this->VScroll, newValue);
  892.                           MoveScrollText();
  893.                       }
  894.                     GetMouse (&tempPt);
  895.                 }    
  896.           }
  897.     }
  898.     
  899. /*-----------------------------------------------------------------*/
  900.  
  901.     void    CPPText::HPageScroll (long part, long direction)
  902.     /* Scroll the text 1 page either left or right */
  903.     {
  904.         Point    tempPt;
  905.         short    newValue, page;
  906.         TEPtr    TE;
  907.         
  908.         if (this->HScroll && this->TextBlock)
  909.           {
  910.               TE = *this->TextBlock;
  911.               GetMouse (&tempPt);
  912.               while (StillDown())
  913.                 {
  914.                     if (TestControl(this->HScroll, tempPt) == part)
  915.                       {
  916.                           page = direction * ((TE->viewRect.right - 
  917.                                               TE->viewRect.left) / 
  918.                                               (TE->lineHeight - 1));
  919.                           newValue = GetCtlValue (this->HScroll) + page;
  920.                           SetCtlValue (this->HScroll, newValue);
  921.                           MoveScrollText();
  922.                       }
  923.                     GetMouse (&tempPt);
  924.                 }    
  925.           }
  926.     }
  927.  
  928. /*-----------------------------------------------------------------*/
  929.  
  930.     void    CPPText::AdjustScrollBar (void)
  931.     /* This procedure turns the scroll bar off if there are fewer */
  932.     /* lines than space for lines, and turns it on to its maximum */
  933.     /* position if there are more */
  934.     {
  935.         short windowLines,
  936.               currentLines,
  937.               currentWidth;
  938.         TEPtr    TE;
  939.         
  940.         if (this->TextBlock)
  941.           {
  942.               TE = *this->TextBlock;
  943.               
  944.             if (this->VScroll)
  945.               {
  946.                   windowLines = LinesInWindow();
  947.                   currentLines = LinesInText();
  948.                   if (currentLines > windowLines)
  949.                     SetCtlMax (this->VScroll, currentLines - windowLines);
  950.                   else
  951.                     {
  952.                         SetCtlMax (this->VScroll, 0);
  953.                         SetCtlMin (this->VScroll, 0);
  954.                     }
  955.               }
  956.             
  957.             if (this->HScroll)
  958.               {
  959.                   currentWidth = abs((TE->viewRect.right - 
  960.                                      TE->destRect.right) / TE->lineHeight);
  961.                   if (currentWidth)
  962.                     SetCtlMax (this->HScroll, currentWidth);
  963.                   else
  964.                     {
  965.                         SetCtlMax (this->HScroll, 0);
  966.                         SetCtlMin (this->HScroll, 0);
  967.                     }
  968.               }
  969.           }
  970.     }
  971.  
  972. /*-----------------------------------------------------------------*/
  973. //
  974. //    Boolean    CPPText::AutoScroll (void)
  975.     /* this is the function which is called if you click in the */
  976.     /* TextEdit field and drag the mouse down or up beyond the */
  977.     /* bottom or top of the window.  It should be set with the */
  978.     /* SetClikLoop function for the TextEdit field you are using */
  979.  /*    {
  980.         RgnHandle    oldClip;
  981.         Point        mouseLoc;
  982.         Rect        textRect;
  983.         Rect        tempRect;
  984.         TEPtr        TE;
  985.         
  986.         if (!this->TextBlock)
  987.           return FALSE;
  988.         TE = *this->TextBlock;
  989.         
  990.         oldClip = NewRgn();
  991.         GetClip (oldClip);
  992.         
  993.         tempRect = TE->viewRect;
  994.         if (this->VScroll)
  995.           UnionRect (&tempRect, &((*this->VScroll)->contrlRect), &tempRect);
  996.         if (this->HScroll)
  997.           UnionRect (&tempRect, &((*this->HScroll)->contrlRect), &tempRect);
  998.         ClipRect (&tempRect);
  999.         GetMouse(&mouseLoc);
  1000.         textRect= TE->viewRect;
  1001.         if (mouseLoc.v < textRect.top)
  1002.           Scroll_Up(this->VScroll, inUpButton);
  1003.         else
  1004.           if (mouseLoc.v > textRect.bottom)
  1005.             Scroll_Down (this->VScroll, inDownButton);
  1006.     
  1007.         if (mouseLoc.h > textRect.right)
  1008.           Scroll_Right (this->HScroll, inDownButton);
  1009.         else
  1010.           if (mouseLoc.h < textRect.left)
  1011.             Scroll_Left (this->HScroll, inUpButton);
  1012.         
  1013.         SetClip (oldClip);
  1014.         DisposeRgn(oldClip);
  1015.         
  1016.         return TRUE;
  1017.     }
  1018.     */
  1019. /*-----------------------------------------------------------------*/
  1020.  
  1021.     void CPPText::DoVScroller (Point clickPt, short part)
  1022.     /* Handle a click in the vertical scroll bar */
  1023.     {
  1024.         long    Result;
  1025.         
  1026.         gCurrentTE = this;
  1027.         
  1028.         if (this->VScroll)
  1029.           {
  1030.             switch (part) {
  1031.                 case inUpButton     :
  1032.                     Result = TrackControl(this->VScroll, clickPt, 
  1033.                                           (ProcPtr)Scroll_Up);
  1034.                     break;
  1035.                 case inDownButton    :
  1036.                     Result = TrackControl(this->VScroll, clickPt, 
  1037.                                           (ProcPtr)Scroll_Down);
  1038.                     break;
  1039.                 case inPageUp        :
  1040.                     VPageScroll (part, 1);
  1041.                     break;
  1042.                 case inPageDown        :
  1043.                     VPageScroll (part, -1);
  1044.                     break;
  1045.                 case inThumb        :
  1046.                     TrackControl (this->VScroll, clickPt, NULL);
  1047.                     MoveScrollText();
  1048.                     break;
  1049.             }
  1050.           }
  1051.     }
  1052.     
  1053. /*-----------------------------------------------------------------*/
  1054.  
  1055.     void CPPText::DoHScroller (Point clickPt, short part)
  1056.     /* Handle a click in the horizontal scroll bar */
  1057.     {
  1058.         long    Result;
  1059.  
  1060.         gCurrentTE = this;
  1061.         
  1062.         if (this->HScroll)
  1063.           {
  1064.             switch (part) {
  1065.                 case inUpButton     :
  1066.                     Result = TrackControl(this->HScroll, clickPt, 
  1067.                                           (ProcPtr)Scroll_Left);
  1068.                     break;
  1069.                 case inDownButton    :
  1070.                     Result = TrackControl(this->HScroll, clickPt, 
  1071.                                           (ProcPtr)Scroll_Right);
  1072.                     break;
  1073.                 case inPageUp        :
  1074.                     HPageScroll (part, -1);
  1075.                     break;
  1076.                 case inPageDown        :
  1077.                     HPageScroll (part, 1);
  1078.                     break;
  1079.                 case inThumb        :
  1080.                     TrackControl (this->HScroll, clickPt, NULL);
  1081.                     MoveScrollText();
  1082.                     break;
  1083.             }
  1084.           }
  1085.     }
  1086.  
  1087. /*-----------------------------------------------------------------*/
  1088.  
  1089.     void CPPText::MakeTEArea (CPPWindow    *OurWindow,
  1090.                                   Rect *ViewArea,
  1091.                                   Rect *DestArea,
  1092.                                   short    maxLength,
  1093.                                   Boolean UseHScroll,
  1094.                                   Boolean UseVScroll,
  1095.                                   short Font, short FSize)
  1096.     {
  1097.         Rect    DestRect = *DestArea;
  1098.         Rect    ViewRect = *ViewArea;
  1099.         Rect    TempRect;
  1100.         GrafPtr    savePort;
  1101.         short    OldFont, OldFace, OldSize;
  1102.         
  1103.         if (!OurWindow)
  1104.           return;
  1105.         this->owningWindow = OurWindow->GetWindow();
  1106.         this->maxTextLen = maxLength;
  1107.         
  1108.         GetPort(&savePort);
  1109.         SetPort (this->owningWindow);
  1110.     
  1111.         // save the font, size and style of the current grafport
  1112.         OldFont = this->owningWindow->txFont;
  1113.         OldSize = this->owningWindow->txSize;
  1114.         
  1115.         // set the font so that the TE area will appear correctly
  1116.         TextFont (Font);
  1117.         TextSize (FSize);
  1118.     
  1119.         // adjust the size of the view rectangle if there are scrollbars
  1120.         if (UseHScroll)
  1121.           ViewRect.bottom -= (kSBarWidth - 1);
  1122.         if (UseVScroll)
  1123.           ViewRect.right -= (kSBarWidth - 1);
  1124.     
  1125.         this->TextBlock = TENew (&DestRect, &ViewRect);
  1126.         if (!this->TextBlock)
  1127.           {    
  1128.               SetPort (savePort);
  1129.               return;
  1130.           }
  1131.                     
  1132.           if (UseVScroll)
  1133.             {
  1134.                 SetRect (&TempRect, ViewRect.right, ViewRect.top-1,
  1135.                          ViewRect.right+16, ViewRect.bottom+1);
  1136.                 this->VScroll = NewControl(this->owningWindow, &TempRect, "\pVScroller",
  1137.                                            TRUE, 0, 0, 0, scrollBarProc, 1101);
  1138.                 if (!this->VScroll)
  1139.                   {
  1140.                       TEDispose(this->TextBlock);
  1141.                       SetPort (savePort);
  1142.                       return;
  1143.                   }
  1144.             }
  1145.           else
  1146.             this->VScroll = NULL;
  1147.  
  1148.           if (UseHScroll)
  1149.             {
  1150.                 SetRect (&TempRect, ViewRect.left-1, ViewRect.bottom,
  1151.                          ViewRect.right+1, ViewRect.bottom + 16);
  1152.                 this->HScroll = NewControl(this->owningWindow, &TempRect, "\pHScroller",
  1153.                                            TRUE, 0, 0, 0, scrollBarProc, 1102);
  1154.                 if (!this->HScroll)
  1155.                   {
  1156.                       TEDispose(this->TextBlock);
  1157.                       if (this->VScroll)
  1158.                         DisposeControl(this->VScroll);
  1159.                       SetPort (savePort);
  1160.                       return;
  1161.                   }
  1162.             }
  1163.           else
  1164.             this->HScroll = NULL;
  1165.             
  1166.          SetMinSize (70, 70);
  1167.          SetMaxSize ((DestArea->right - DestArea->left) + 16,
  1168.                      (DestArea->bottom - DestArea->top) + 16);
  1169.  
  1170.         SetClikLoop (AutoScroll, this->TextBlock);
  1171.         
  1172.         // restore the original font and size
  1173.         TextSize (OldSize);
  1174.         TextFont (OldFont);
  1175.         
  1176.         // restore the saved port
  1177.         SetPort (savePort);
  1178.     }
  1179.  
  1180. /*-----------------------------------------------------------------*/
  1181.  
  1182.  
  1183.